package com.glsc.ngateway.oaflow.config;

import com.glsc.ngateway.common.xir.config.XirDatasourceConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
@Import({XirDatasourceConfig.class})
public class DatasourceConfig {

    @Primary
    @Bean(name = "datasourceMysql")
    @ConfigurationProperties("spring.datasource.mysql")
    public DataSource datasourceMysql() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "datasourceOracle")
    @ConfigurationProperties("spring.datasource.oracle")
    public DataSource datasourceOracle() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "datasourceOracleSecond")
    @ConfigurationProperties("spring.datasource.oraclesecond")
    public DataSource datasourceOracleSecond() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 多数据源，自定义mysql/oracle的连接属性
     */
    @Primary
    @Bean(name = "entityManagerFactoryMysql")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryMysql(EntityManagerFactoryBuilder builder) {
        LocalContainerEntityManagerFactoryBean emf = builder
                .dataSource(datasourceMysql())
                .packages("com.glsc.ngateway.common.base.domain.mysql.gateway") //设置实体类所在位置
                .persistenceUnit("mysqlPersistenceUnit")
                .build();
        Properties properties = new Properties();
        //方言
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        //不需要自动创建、更新、验证数据库表结构
        properties.setProperty("hibernate.hbm2ddl.auto", "none");
        properties.setProperty("hibernate.physical_naming_strategy", "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
        //输出SQL
        properties.setProperty("hibernate.show_sql", "false");
        properties.setProperty("hibernate.format_sql", "true");
        //懒加载
        properties.setProperty("hibernate.enable_lazy_load_no_trans", "true");
        emf.setJpaProperties(properties);
        return emf;
    }

    @Bean(name = "entityManagerFactoryOracle")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryOracle(EntityManagerFactoryBuilder builder,
                                                                             @Qualifier("routingDataSource") DataSource routingDataSource) {
        LocalContainerEntityManagerFactoryBean emf = builder
                .dataSource(routingDataSource)
                .packages("com.glsc.ngateway.common.base.domain.oracle.ecology") //设置实体类所在位置
                .persistenceUnit("oraclePersistenceUnit")
                .build();
        Properties properties = new Properties();
        //方言
//        properties.setProperty("hibernate.dialect","org.hibernate.dialect.OracleDialect");
        properties.setProperty("hibernate.dialect", "com.glsc.ngateway.oaflow.utils.CustomOracleDialect");//解决oa oracle sequence min_value过小，重载dialect

        //不需要自动创建、更新、验证数据库表结构
        properties.setProperty("hibernate.hbm2ddl.auto", "none");
        properties.setProperty("hibernate.physical_naming_strategy", "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
        //输出SQL
        properties.setProperty("hibernate.show_sql", "true");
        properties.setProperty("hibernate.format_sql", "true");
        //懒加载
        properties.setProperty("hibernate.enable_lazy_load_no_trans", "true");
        emf.setJpaProperties(properties);
        return emf;
    }

    @Primary
    @Bean(name = "entityManagerMysql")
    public EntityManager entityManagerMysql(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryMysql(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerOracle")
    public EntityManager entityManagerOracle(EntityManagerFactoryBuilder builder,@Qualifier("routingDataSource") DataSource routingDataSource) {
        return entityManagerFactoryOracle(builder,routingDataSource).getObject().createEntityManager();
    }

    @Primary
    @Bean(name = "transactionManagerMysql")
    public PlatformTransactionManager transactionManagerMysql(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryMysql(builder).getObject());
    }

    @Bean(name = "transactionManagerOracle")
    public PlatformTransactionManager transactionManagerOracle(EntityManagerFactoryBuilder builder,@Qualifier("routingDataSource") DataSource routingDataSource) {
        return new JpaTransactionManager(entityManagerFactoryOracle(builder,routingDataSource).getObject());
    }

    @Bean(name = "jdbcTemplateOracle")
    JdbcTemplate jdbcTemplateOracle(@Qualifier("routingDataSource") DataSource routingDataSource) {
        return new JdbcTemplate(routingDataSource);
    }

    @Bean(name = "namedJdbcTemplateEcology")
    NamedParameterJdbcTemplate namedParameterJdbcTemplate(@Qualifier("routingDataSource") DataSource routingDataSource) {
        return new NamedParameterJdbcTemplate(routingDataSource);
    }

    @Bean
    public DataSource routingDataSource(@Qualifier("datasourceOracle") DataSource primaryDataSource,
                                        @Qualifier("datasourceOracleSecond") DataSource secondaryDataSource) {
        AbstractRoutingDataSource routingDataSource = new RoutingDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("primary", primaryDataSource);
        targetDataSources.put("secondary", secondaryDataSource);

        routingDataSource.setTargetDataSources(targetDataSources);
        routingDataSource.setDefaultTargetDataSource(primaryDataSource);

        return routingDataSource;
    }

    @Bean
    public DataSource dataSource(DataSource routingDataSource) {
        return routingDataSource;
    }
}
